iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Software Development

系統設計就像九頭蛇:打造社群網站的 30 天系列 第 5 篇

Day 5 一台 Server 不夠用:Vertical Scaling vs Horizontal Scaling

  • 分享至 

  • xImage
  •  

這幾天我們把最陽春的 PokeThreads 做出來了,也解決了 Feed 該回傳什麼內容的問題,但整個架構其實還停留在最原始的狀態:

瀏覽器 -> Server -> Database

只有一台 Server,所有使用者的 Request 都打到同一個地方。當時的假設是使用者只有 100 人,這台 Server 綽綽有餘,但如果使用者從 100 人變成 10 萬人、100 萬人呢?

即使 Database 還撐得住,這一台 Server 本身的運算能力終究有極限,於是我們要面對一個很基本、卻也很重要的問題:

當一台 Server 不夠用了,我們該怎麼辦?

把 Server 變強

假設現在的 Server 規格是:

  • 4 CPU
  • 8 GB RAM

流量增加時,最直接的想法就是換一台更強的機器:

  • 16 CPU
  • 64 GB RAM

這種做法叫做 Vertical Scaling(垂直擴展),也稱為 Scale Up。

它最大的優點是完全不用改架構:

原本:瀏覽器 -> Server      -> Database
現在:瀏覽器 -> 更強的 Server -> Database

不需要處理 Request 該分配到哪一台,也不用多準備任何新元件。

自助餐裝不下?盤子加大就對了,就是這麼簡單粗暴。

對早期的小型系統來說,這其實是很合理的第一步。

Vertical Scaling 的問題

但 Vertical Scaling 有兩個很明顯的天花板。

第一,硬體有極限。CPU、Memory 不可能無限往上疊,即使雲端廠商能提供非常誇張規格的機器,也不代表我們能無限制地升級下去。

第二,也是更關鍵的一個問題:Single Point of Failure(單點故障)。

現在所有 Request 都由這一台 Server 處理,可是一旦它當機,不管是網路問題、硬體故障還是 OS 出包,所有使用者都會連不上我們的服務,整個網站直接烙賽,SRE 頭殼𢯾咧燒。

就算這台 Server 效能再好,只要世界上只有一台,風險就一直都在。

增加 Server 的數量

既然把單一機器越養越大會撞到天花板,那換個方向:不要只養一隻大的,改養一群。

原本只有:

Server 1

現在變成:

Server 1
Server 2
Server 3

這就是 Horizontal Scaling(水平擴展),也叫 Scale Out。

但問題馬上就來了:現在有三台 Server,使用者的 Request 到底該送去哪一台?

Load Balancer 幫助分流

這時候需要引入一個新元件:Load Balancer(負載平衡器)。

可以把它想成銀行大廳的號碼牌機,客人(Request)進門先抽號碼牌,系統再把客人平均分配給空著的櫃檯(Server),客人不需要知道今天有幾位櫃員在上班,只要跟著號碼牌走就好。

Load Balancer 放在 Client 與 Application Server 之間:

Load Balancer 放在 Client 與 Application Server 之間的架構圖

使用者只知道自己連上了「一個服務」,DNS 解析到的其實是 Load Balancer 的位址,實際上背後有幾台 Server 在工作,對使用者來說是透明的。

最簡單的分配方式:Round Robin

假設現在有 Server A、B、C,最直覺的分配方式是輪流發放號碼牌:

Request 1 → Server A
Request 2 → Server B
Request 3 → Server C
Request 4 → Server A
Request 5 → Server B
Request 6 → Server C

這種做法就是 Round Robin,既簡單又公平,是很多 Load Balancer 的預設策略。

Health Check:不能把客人排到打烊的櫃檯

銀行號碼牌機還有一個很重要的功能:如果某個櫃檯的行員臨時離開,系統不會再把新客人分配過去。

Load Balancer 也是一樣的邏輯,它會定期對每一台 Server 送出 Health Check(健康檢查),確認對方是否還活著、是否還能正常處理 Request。

假設 Server B 掛掉了:

Browser
   ↓              ┌── Server A ✓
Load Balancer ────┼── Server B ✗
                  └── Server C ✓

Load Balancer 一旦偵測到 Server B 沒有回應,就會停止把新 Request 導向它,直到它恢復正常為止。這讓系統具備了初步的 Fault Tolerance(容錯能力),少了一台 Server,服務還是能繼續運作,只是整體處理能力會下降。

現在的架構

加上 Load Balancer 和多台 Server 之後,架構從最初的樣子:

瀏覽器 -> Server -> Database

演化成:

瀏覽器 -> Load Balancer -> Server(多台)-> Database

具體來說,我們現在具備了:

  • 多台 Application Server
  • Load Balancing
  • Health Check
  • 初步的 Fault Tolerance

Vertical Scaling vs Horizontal Scaling

把兩種擴展方式放在一起比較:

Vertical Scaling Horizontal Scaling
做法 把機器變強 增加機器數量
別名 Scale Up Scale Out
架構複雜度 低 較高(需要 Load Balancer)
擴展上限 受硬體限制 可持續增加節點
Fault Tolerance 較弱(單點故障) 較容易做到
適合場景 小型、早期系統 高流量、大型系統

要提醒的是,這不是「Horizontal Scaling 永遠比較好」的結論。

實務上兩者經常一起使用,例如先把單台 Server 規格拉到一個合理甜蜜點,再用多台這種規格的機器做水平擴展。

真正該問的問題從來不是「哪一種比較好」,而是現在的瓶頸,需要哪一種擴展方式來解決。

小結

今天解決的是 Application Server 這一層的擴展問題,但這裡其實埋了一個還沒拆開的細節。

回想 Day 2,我們是把使用者的登入狀態(Session)直接存在 Server 的 Memory 裡。

現在 Server 從一台變成了三台,如果 Pikachu 的第一個 Request 被分配到 Server A,第二個 Request 卻被分配到 Server B,而 Server B 的 Memory 裡根本沒有 Pikachu 的 Session,它還認得出這是誰嗎?

這是明天要處理的問題。


上一篇
Day 4 REST vs GraphQL:前後端到底該怎麼聊天?
下一篇
Day 6 Session 要放哪?
系列文
系統設計就像九頭蛇:打造社群網站的 30 天 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言